package edu.pw.p2pclient.data;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

import android.os.Environment;

public class TreeNode extends Node implements Serializable {
	private static final long serialVersionUID = -7725358362720778348L;

	public static final String ROOT_PATH = Environment
			.getExternalStorageDirectory().getAbsolutePath();

	private HashMap<String, TreeNode> mChildren;

	public TreeNode() {

		super(ROOT_PATH, Node.FOLDER);
		mChildren = null;
	}

	public TreeNode(Node node) {

		super(node);
		mChildren = null;
	}

	public TreeNode(File file, SharingInfo info) {

		super(file, info);
		mChildren = null;
	}

	@Override
	public boolean equals(Object o) {

		if (o == null || o.getClass() != getClass())
			return false;
		TreeNode tmp = (TreeNode) o;
		boolean res = tmp.getFullPath().equals(getFullPath())
				&& tmp.mChildren == null && tmp.mChildren.equals(mChildren);
		return res;
	}

	public void addChild(TreeNode node) {

		assert (!node.isFile());

		if (mChildren == null)
			mChildren = new HashMap<String, TreeNode>(2);

		String fullPath = getFullPath();
		if (node.getPath().equals(fullPath)) {
			TreeNode tmp = mChildren.get(node.getName());
			if (tmp == null)
				mChildren.put(node.getName(), node);
			else
				tmp.setSharingInfo(node.mSharingInfo);
		} else {
			if (!fullPath.endsWith("/"))
				fullPath += "/";
			int pos = node.getPath().indexOf("/", fullPath.length());
			if (pos == -1)
				pos = node.getPath().length();
			String newPath = node.getPath().substring(fullPath.length(), pos);
			TreeNode tmp = mChildren.get(newPath);
			if (tmp == null) {
				mChildren.put(newPath, new TreeNode(new File(getFullPath()
						+ "/" + newPath), node.getSharingInfo()));
				tmp = mChildren.get(newPath);
			}
			tmp.addChild(node);
		}
	}

	public Node getChild(Resource res) {
		return getChild(res, ROOT_PATH);
	}

	private Node getChild(Resource res, String currentPath) {

		Node retVal = null;
		if (mChildren == null)
			return null;
		for (TreeNode node : mChildren.values()) {
			if (retVal != null)
				return retVal;
			if (!node.isFile())
				retVal = node.getChild(res, node.getPath());
			else if (node.isShared() && res.equals(node))
				retVal = node;
		}
		return retVal;
	}

	public void removeChild(Node node) {

		String fullPath = getFullPath();
		if (node.getPath().equals(fullPath))
			mChildren.remove(node.getName());
		else {
			if (!fullPath.endsWith("/"))
				fullPath += "/";
			int pos = node.getPath().indexOf("/", fullPath.length());
			if (pos == -1)
				pos = node.getPath().length();
			String newPath = node.getPath().substring(fullPath.length(), pos);
			TreeNode tmp = mChildren.get(newPath);
			if (tmp != null)
				tmp.removeChild(node);
		}
	}

	public HashMap<String, Node> getItemsFrom(String path) {

		String fullPath = getFullPath();
		if (fullPath.equals(path))
			return (mChildren == null ? new HashMap<String, Node>()
					: new HashMap<String, Node>(mChildren));
		else {
			if (!fullPath.endsWith("/"))
				fullPath += "/";
			int pos = path.indexOf("/", fullPath.length());
			if (pos == -1)
				pos = path.length();
			String newPath = path.substring(fullPath.length(), pos);
			TreeNode tmp = (mChildren == null ? null : mChildren.get(newPath));
			return (tmp == null ? new HashMap<String, Node>() : tmp
					.getItemsFrom(path));
		}
	}

	public ArrayList<Node> getShared(boolean bt, boolean wifi, boolean push) {
		ArrayList<Node> list = new ArrayList<Node>();
		if (mChildren == null)
			return list;
		for (TreeNode node : mChildren.values()) {
			if (!node.isFile())
				list.addAll(node.getShared(bt, wifi, push));
			else if ((node.isBtShared() && bt) || (node.isWifiShared() && wifi)
					|| (node.isPush() && push))
				list.add(node);
		}
		return list;
	}

	@Override
	public int hashCode() {

		return (mChildren == null ? 0 : mChildren.hashCode())
				+ super.hashCode();
	}

}
